/*
 * @(#)Cam.java
 * 
 * Create Version: 1.0.0
 * Author: James Liu
 * Create Date: 2009-12-09
 * 
 * Copyright (c) 2009 ASPire Information Technologies Ltd. All Right Reserved.
 */
package com.aspire.boc.mms.wmf.cam;


import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.servlet.http.HttpSession;
import javax.swing.tree.DefaultMutableTreeNode;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlrpc.XmlRpcClient;
import org.apache.xmlrpc.XmlRpcException;

import com.aspire.boc.mms.wmf.util.Configuration;
import com.aspire.boc.mms.wmf.util.ThreadLocalHttpSession;
import com.aspire.cam.rpc.client.XmlRpcClientProxy;


public class CamUtil {
    
    private static Log log = LogFactory.getLog(CamUtil.class);
    
    private static String url = Configuration.getConfiguration("system.permission.url");
    private static String system_def = Configuration.getConfiguration("system.permission.system_def");
	// 取得用户信息
    private static XmlRpcClient client = null;
    
    static {
    	try {
			client = new XmlRpcClient(url);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    public static Set<Group> getCacheGroupsByUserName(String userName){
    	Set<User>  users = CamCache.getInstance().getUsers();
    	if(null==users){
    		CamCache.getInstance().load();
    	}
    	Set<Group> result = null;
    	for(User user : users){
    		 if (user.getName().equals(userName)) {
                 result = user.getGroups();
                 break;
    		 }
    	}
    	
        return result;
    }
    
    /**
     * 
     * @Title: getCacheGroups 
     * @Description: TODO(获取所有组信息) 
     * @return
     */
    public static Set<Group> getCacheGroups(){
    	return CamCache.getInstance().getGroups();
    }
    
    /**
     * {group_name=root, user_name=chenjianjun, group_id=670, group_descr=系统根组,
     *  parent_group_id=0, level_id=1, system_def=MMS_SOMP}

     * @Title: getGroupsByUserName 
     * @Description: TODO(根据用户名获取组) 
     * @param userName
     * @return
     */
    public static Set<Group> getGroupsByUserName(String userName){
        Set<Group> results = new LinkedHashSet<Group>();
		try {
		    Vector<String> params = new Vector<String>();
		    params.add(system_def);
		    params.add(userName);
		    Vector<?> oo = (Vector<?>) client.execute("UserService.getUserGroupList", params);
            for(Object o  : oo){
            	System.out.println(o instanceof Map);
            	System.out.println(o instanceof HashMap);
            	System.out.println(o instanceof HashMap<?,?>);
            	Hashtable<?, ?> camClientGroupPO = (Hashtable<?, ?>) o;
            	System.out.println(camClientGroupPO);
            	 Group group = new Group();
                 group.setId((Integer) camClientGroupPO.get("group_id"));
                 group.setName((String) camClientGroupPO.get("group_name"));
                 group.setAdministrator((String) camClientGroupPO.get("user_name"));
                 group.setLevel((Integer) camClientGroupPO.get("level_id"));
                 group.setParentId((Integer) camClientGroupPO.get("parent_group_id"));
                 group.setSystemDef((String) camClientGroupPO.get("system_def"));
                 group.setDesc((String) camClientGroupPO.get("group_descr"));
                 results.add(group);
            }
        }catch(Exception e){
        	e.printStackTrace();
        }
		return results;
    }
    
    /**
     * 根据用户名得到用户信息
     * @Title: getGroups 
     * @Description: TODO(这里用一句话描述这个方法的作用) 
     * @return
     */
    public static User getUser(String username) {
        
        User result = null;
        
        Iterator<User> userIter = CamCache.getInstance().getUsers().iterator();
        while (userIter.hasNext()) {
            User user = userIter.next();
            if (user.getName().equals(username)) {
                result = user;
                break;
            }
        }
        
        return result;
    }
    
    @SuppressWarnings("unchecked")
    public static List<Menu> getPreorderMenus(String username) {
        
        List<Menu> cache = null;
        
        HttpSession session = ThreadLocalHttpSession.getSession();
        if (session != null) {
            try {
                cache = (List<Menu>) session.getAttribute("cam.preordermenus");
            } catch (Exception e) {}
        }
        
        if (cache == null) {
            cache = new ArrayList<Menu>();
            
            Object rpcResult = callCamRpc("UserMenuService.getMenuList", null);
            if (rpcResult != null) {
                Object[] resultArray = (Object[]) rpcResult;
                
                for (Object result : resultArray) {
                    Map<?, ?> menuPO = (Map<?, ?>) result;
                    Object[] params = new Object[] {menuPO.get("menu_name"), username};
                    Object menuItemRpcResult = callCamRpc("UserMenuService.getMenuItemTree", params);
                    if (menuItemRpcResult != null) {
                        DefaultMutableTreeNode root = (DefaultMutableTreeNode) menuItemRpcResult;
                        Enumeration<?> nodeEnum = root.preorderEnumeration();
                        while (nodeEnum.hasMoreElements()) {
                            DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodeEnum.nextElement();
                            if (node.getUserObject() != null) {
                                Map<?, ?> menuItemPO = (Map<?, ?>) node.getUserObject();
                                Menu menu = generateMenu(menuItemPO);
                                cache.add(menu);
                            }
                        }
                    }
                }
                
                if (session != null) {
                    session.setAttribute("cam.preordermenus", cache);
                }
            }
        }
        
        return cache;
    }
    
    @SuppressWarnings("unchecked")
    public static List<Menu> getMenus(String username) {
        
        List<Menu> cache = null;
        
        HttpSession session = ThreadLocalHttpSession.getSession();
        if (session != null) {
            try {
                cache = (List<Menu>) session.getAttribute("cam.menus");
            } catch (Exception e) {}
        }
        
        if (cache == null) {
            cache = new ArrayList<Menu>();
            
            Object rpcResult = callCamRpc("UserMenuService.getMenuList", null);
            if (rpcResult != null) {
                Object[] resultArray = (Object[]) rpcResult;
                
                for (Object result : resultArray) {
                    Map<?, ?> menuPO = (Map<?, ?>) result;
                    Object[] params = new Object[] {menuPO.get("menu_name"), username};
                    Object menuItemRpcResult = callCamRpc("UserMenuService.getMenuItemTree", params);
                    if (menuItemRpcResult != null) {
                        DefaultMutableTreeNode root = (DefaultMutableTreeNode) menuItemRpcResult;
                        Map<Integer, Menu> menuMap = new LinkedHashMap<Integer, Menu>();
                        List<Menu> menuList = new LinkedList<Menu>();
                        Enumeration<?> nodeEnum = root.preorderEnumeration();
                        while (nodeEnum.hasMoreElements()) {
                            DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodeEnum.nextElement();
                            if (node.getUserObject() != null) {
                                Map<?, ?> menuItemPO = (Map<?, ?>) node.getUserObject();
                                Menu menu = generateMenu(menuItemPO);
                                menuMap.put(menu.getId(), menu);
                                menuList.add(menu);
                            }
                        }
                        for (Menu menu : menuList) {
                            Menu parent = menuMap.get(menu.getParentId());
                            if (parent != null) {
                                menu.setParent(parent);
                                parent.getChildren().add(menu);
                            }
                        }
                        for (Menu menu : menuList) {
                            if (menu.getParent() == null) {
                                cache.add(menu);
                            }
                        }
                    }
                }
                
                if (session != null) {
                    session.setAttribute("cam.menus", cache);
                }
            }
        }
        
        return cache;
    }
    
    @SuppressWarnings("unchecked")
    public static Set<Permission> getPermissions(String username) {
        
        Set<Permission> cache = null;
        
        HttpSession session = ThreadLocalHttpSession.getSession();
        if (session != null) {
            try {
                cache = (Set<Permission>) session.getAttribute("cam.permissions");
            } catch (Exception e) {}
        }
        
        if (cache == null) {
            cache = new LinkedHashSet<Permission>();
            
            Object[] params = new Object[] {username};
            Object rpcResult = callCamRpc("UserPermService.getPermList", params);
            if (rpcResult != null) {
                Object[] resultArray = (Object[]) rpcResult;
                
                for (Object result : resultArray) {
                    cache.add(generatePermission((Map<?, ?>) result));
                }
                
                if (session != null) {
                    session.setAttribute("cam.permissions", cache);
                }
            }
        }
        
        return cache;
    }
    
    public static Set<Permission> getPermissions(String username, String resourceString) {
        
        Set<Permission> result = new LinkedHashSet<Permission>();
        
        Set<Permission> permissions = getPermissions(username);
        for (Permission permission : permissions) {
            if (permission.getResourceString().equals(resourceString)) {
                result.add(permission);
            }
        }
         
        return result;
    }
    
    public static boolean checkPermission(String username, String resourceString, String operation) {
        
        boolean result = false;
        
        Set<Permission> permissions = getPermissions(username, resourceString);
        for (Permission permission : permissions) {
            if (permission.getOperation().equals(operation)) {
                result = true;
                break;
            }
        }
        
        /*if (!result) {
            Object[] params = new Object[] {resourceString, operation, username};
            Object rpcResult = callCamRpc("UserPermService.checkPerm", params);
            if (rpcResult == null) {
                result = false;
            } else {
                result = (Boolean) rpcResult;
            }
        }*/
        
        return result;
    }
    
    public static Set<User> getVisualUsers(String username) {
        
        Set<User> result = new LinkedHashSet<User>();
        
        User user = getUser(username);
        if (user != null) {
            Set<Group> groups = user.getGroups();
            for (Group group : groups) {
                result.addAll(group.getUsers());
                result.addAll(getSubGroupUsers(group));
            }
        }
        
        return result;
    }
    
    public static List<String> getVisualUsernames(String username) {
        
        List<String> result = new LinkedList<String>();
        
        Set<User> users = getVisualUsers(username);
        for (User user : users) {
            result.add(user.getName());
        }
        
        return result;
    }
    
    public static Set<User> getReferenceUsers(String username) {
        
        Set<User> result = new LinkedHashSet<User>();
        
        User user = getUser(username);
        if (user != null) {
            Set<Group> groups = user.getGroups();
            for (Group group : groups) {
                result.addAll(getParentGroupUsers(group));
                result.addAll(group.getUsers());
                result.addAll(getSubGroupUsers(group));
            }
        }
        
        return result;
    }
    
    public static List<String> getReferenceUsernames(String username) {
        
        List<String> result = new LinkedList<String>();
        
        Set<User> users = getReferenceUsers(username);
        for (User user : users) {
            result.add(user.getName());
        }
        
        return result;
    }
    
    private static Set<User> getParentGroupUsers(Group group) {
        
        Set<User> result = new LinkedHashSet<User>();
        
        Group parentGroup = group.getParent();
        if (parentGroup != null) {
            result.addAll(getParentGroupUsers(parentGroup));
            result.addAll(parentGroup.getUsers());
        }
        
        return result;
    }
    
    private static Set<User> getSubGroupUsers(Group group) {
        
        Set<User> result = new LinkedHashSet<User>();
        
        Set<Group> subGroups = group.getChildren();
        for (Group subGroup : subGroups) {
            result.addAll(subGroup.getUsers());
            result.addAll(getSubGroupUsers(subGroup));
        }
        
        return result;
    }
    
	private static Object callCamRpc(String method, Object[] params) {
        
        Object result = null;
        String xmlRpcServerUrl = Configuration.getConfiguration("system.permission.url");
        String system_def = Configuration.getConfiguration("system.permission.system_def");
        
        Object[] rpcParams = null;
        if (params == null) {
            rpcParams = new Object[] {system_def};
        } else {
            rpcParams = new Object[params.length + 1];
            rpcParams[0] = system_def;
            for (int i=0; i<params.length; i++) {
                rpcParams[i + 1] = params[i];
            }
        }
        
        XmlRpcClientProxy clientProxy;
        try {
            clientProxy = new XmlRpcClientProxy(xmlRpcServerUrl);
            result = clientProxy.execute(method, rpcParams);
        } catch (MalformedURLException e) {
            log.error("CAM xml rpc server url error!", e);
        } catch (XmlRpcException e) {
            log.error("CAM xml rpc service error!", e);
        }
        
        return result;
    }
    
    private static Menu generateMenu(Map<?, ?> menuItemPO) {
        
        Menu result = null;
        
        if (menuItemPO != null) {
            result = new Menu();
            result.setId((Integer) menuItemPO.get("menu_item_id"));
            result.setName((String) menuItemPO.get("menu_item_name"));
            result.setUrl((String) menuItemPO.get("menu_url"));
            result.setTarget((String) menuItemPO.get("target"));
            result.setIcon((String) menuItemPO.get("menu_item_icon"));
            result.setTip((String) menuItemPO.get("menu_item_tip"));
            result.setLevel((Integer) menuItemPO.get("level_id"));
            result.setParentId((Integer) menuItemPO.get("parent_item_id"));
            result.setParent(null);
            result.setOrder((Integer) menuItemPO.get("menu_item_order"));
        }
        
        return result;
    }
    
    private static Permission generatePermission(Map<?, ?> permPO) {
        
        Permission result = null;
        
        if (permPO != null) {
            result = new Permission();
            result.setId((Integer) permPO.get("perm_id"));
            result.setResourceName((String) permPO.get("res_name"));
            result.setResourceString((String) permPO.get("res_string"));
            result.setResourceType((Integer) permPO.get("res_type_id"));
            result.setOperation((String) permPO.get("operation"));
            result.setFineGrained4Bool((Boolean) permPO.get("fine_grained4Bool"));
            result.setDesc((String) permPO.get("perm_descr"));
            result.setSystemDef((String) permPO.get("system_def"));
        }
        
        return result;
    }
}